﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace FtpCrawler
{
    public class FtpFileParserInUnixStyle : IFtpFileParser
    {
        /// <summary>
        /// 解析Unix格式的ftp文件列表
        /// </summary>
        /// <remarks>参考：.net sdk sample:FTPExplorerSample列表格式解析</remarks>
        /// <param name="line"></param>
        /// <param name="path"></param>
        /// <returns></returns>
        public FtpFileInfo ParseFile(string line, string path)
        {
            try
            {
                FtpFileInfo fileInfo = new FtpFileInfo();
                fileInfo.Path = path;
                if (line[0] == '-' || line[0] == 'd')
                {
                    // 如果文件为一般文件或目录，意为正确的文件格式
                    string str = line.Trim();
                    fileInfo.AccessMode = str.Substring(0, 9);
                    fileInfo.IsFile = (fileInfo.AccessMode[0] != 'd');
                    this.CutSubStringFromStringWithTrim(ref str, ' ', 0);
                    fileInfo.NumLinks = int.Parse(this.CutSubStringFromStringWithTrim(ref str, ' ', 0));
                    fileInfo.Owner = this.CutSubStringFromStringWithTrim(ref str, ' ', 0);
                    fileInfo.Group = this.CutSubStringFromStringWithTrim(ref str, ' ', 0);
                    fileInfo.Size = long.Parse(this.CutSubStringFromStringWithTrim(ref str, ' ', 0));
                    fileInfo.ModifiedTime = this.GetModifiedTimeFromString(ref str);
                    fileInfo.Filename = str;
                }
                else
                {
                    fileInfo.Filename = "";
                }
                return fileInfo;
            }
            catch (Exception ex)
            {
                // 文件解析失败，返回null
                return null;
            }
        }

        /// <summary>
        /// 去掉字符串前面的一部分
        /// </summary>
        /// <remarks>参考：.net sdk sample:FTPExplorerSample列表格式解析</remarks>
        /// <param name="s">指定字符串，注意会返回</param>
        /// <param name="c">用来分隔的字符</param>
        /// <param name="startIndex">起始位置</param>
        /// <returns>去掉的字符串</returns>
        private string CutSubStringFromStringWithTrim(ref string s, char c, int startIndex)
        {
            int pos = s.IndexOf(c, startIndex);
            string refStr = s.Substring(0, pos);
            s = (s.Substring(pos)).Trim();
            return refStr;
        }

        /// <summary>
        /// 从字符串中获取修改时间
        /// </summary>
        /// <remarks>参考：CodeProject下的LightFTPClient项目中的LightFTPClient.Form1.parseUnixData(string text)</remarks>
        /// <param name="str">指定字符串，以日期字符串开头</param>
        /// <returns></returns>
        private DateTime GetModifiedTimeFromString(ref string str)
        {
            /*
            string month = "(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)";
            string space = @"(\040)+";
            string day = "([0-9][1-3][0-9])";
            string year = "[1-2][0-9]{3}";
            string time = "[0-9]{1,2}:[0-9]{2}";
            Regex dateTimeRegex = new Regex(month + space + day + space + "(" + year + "|" + time + ")", RegexOptions.IgnoreCase);
            Match match = dateTimeRegex.Match(str);
            */
            int year = 0;
            int hour = 0, minute = 0;
            string month = this.CutSubStringFromStringWithTrim(ref str, ' ', 0);
            string day = this.CutSubStringFromStringWithTrim(ref str, ' ', 0);
            string tmp = this.CutSubStringFromStringWithTrim(ref str, ' ', 0);
            if (tmp.IndexOf(':') == -1)
            {
                year = int.Parse(tmp);    // 字符串中包含年份，则将没有时间字段
            }
            else
            {
                year = DateTime.Now.Year;
                int pos = tmp.IndexOf(':');
                hour = int.Parse(tmp.Substring(0, pos));
                minute = int.Parse(tmp.Substring(pos + 1));
            }

            DateTime dt = DateTime.Parse(month + " " + day + " " + year, new CultureInfo("en-US"));
            if (dt.Month > DateTime.Now.Month ||
                (dt.Month == DateTime.Now.Month && dt.Day > DateTime.Now.Day))
            {
                year--;
            }
            dt = new DateTime(year, dt.Month, dt.Day, hour, minute, 0);
            return dt;
        }
    }
}
